package cn.sunshine.ymcc.service.impl;

import cn.sunshine.ymcc.CourseDoc;
import cn.sunshine.ymcc.domain.*;
import cn.sunshine.ymcc.dto.CourseAddDto;
import cn.sunshine.ymcc.fegin.MediaFeign;
import cn.sunshine.ymcc.fegin.SearchFeign;
import cn.sunshine.ymcc.mapper.CourseMapper;
import cn.sunshine.ymcc.result.JSONResult;
import cn.sunshine.ymcc.service.*;
import cn.sunshine.ymcc.util.AssertUtil;
import cn.sunshine.ymcc.vo.CourseDetailInfoVo;
import cn.sunshine.ymcc.vo.CourseInfosTotalAmountVo;
import cn.sunshine.ymcc.vo.CourseInfosVo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Mr.Jiang
 * @since 2022-08-08
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ICourseService courseService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private SearchFeign searchFeign;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ICourseChapterService courseChapterService;
    @Autowired
    private MediaFeign mediaFeign;

    @Override
    @Transactional
    public void save(CourseAddDto courseAddDto) {
        Course courseTemp = courseAddDto.getCourse();
        CourseDetail courseDetailTemp = courseAddDto.getCourseDetail();
        CourseMarket courseMarketTemp = courseAddDto.getCourseMarket();
        List<Long> teacharIds = courseAddDto.getTeacharIds();
        CourseResource courseResourceTemp = courseAddDto.getCourseResource();
        // 业务合法校
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", courseTemp.getName());
        Course course1 = selectOne(wrapper);
        AssertUtil.isNull(course1, "课程已经存在");


        // 课程基本信息
        Course course = new Course();
        course.setStatus(Course.STATE_OFF_LINE);
        Long loginId = 1L;
        course.setLoginId(loginId);
        String loginUserName = "小碗";
        course.setLoginUserName(loginUserName);

        course.setEndTime(courseTemp.getEndTime());
        course.setCourseTypeId(courseTemp.getCourseTypeId());
        course.setForUser(courseTemp.getForUser());
        course.setGradeId(courseTemp.getGradeId());
        course.setGradeName(courseTemp.getGradeName());
        course.setName(courseTemp.getName());
        course.setPic(courseTemp.getPic());
        course.setStartTime(courseTemp.getStartTime());
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);
        String collect = teachers.stream().map(teacher -> teacher.getName()).collect(Collectors.joining(","));
        course.setTeacherNames(collect);
        courseService.insert(course);
        // 课程详情

        CourseDetail courseDetail = new CourseDetail();
        courseDetail.setId(course.getId());
        courseDetail.setDescription(courseDetailTemp.getDescription());
        courseDetail.setIntro(courseDetailTemp.getIntro());
        courseDetailService.insert(courseDetail);
        // 课程销售
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setId(course.getId());
        courseMarket.setCharge(courseMarketTemp.getCharge());
        courseMarket.setPrice(courseMarketTemp.getPrice());
        courseMarket.setPriceOld(courseMarketTemp.getPriceOld());
        courseMarket.setQq(courseMarketTemp.getQq());
        courseMarket.setValidDays(courseMarketTemp.getValidDays());
        courseMarketService.insert(courseMarket);
        // 课程资源
        CourseResource courseResource = new CourseResource();
        // courseResource.setId(course.getId());
        courseResource.setCourseId(course.getId());
        courseResource.setResources(courseResourceTemp.getResources());
        courseResource.setType(courseResourceTemp.getType());
        courseResourceService.insert(courseResource);
        // 课程统计
        CourseSummary summary = new CourseSummary();
        summary.setId(course.getId());
        courseSummaryService.insert(summary);
        // 课程讲师
        for (Long teacharId : teacharIds) {
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setTeacherId(teacharId);
            courseTeacher.setCourseId(course.getId());
            courseTeacherService.insert(courseTeacher);

        }
        // 课程类型表中的课程数量+1
        // 通过传过来的课程类型ID查找是否有该类型的课程类型
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        // 断言工具使用
        AssertUtil.isNotNull(courseType, "课程类型不存在，请仔细查找");
        courseType.setTotalCount(courseType.getTotalCount() + 1);
        courseTypeService.updateById(courseType);
    }

    /*
     * @Title: onLineCourse
     * @Description: 课程上架
     * @Author: Mr.Jiang
     * @Version: 1.0
     * @Date:  2022/8/14 17:02
     * @Parameters: [courseId]
     * @Return void
     */
    @Override
    @Transactional
    public void onLineCourse(Long courseId) {
        // 1.参数校验
        AssertUtil.isNotNull(courseId, "课程ID不能为空");
        // 2.业务校验（查找的课程是否存在）
        Course course = courseService.selectById(courseId);
        AssertUtil.isNotNull(course, "你查找的课程不存在");
        // 3.若存在那么就查看他的状态
        boolean b = course.getStatus() == Course.STATE_ON_LINE;
        if (b) {
            throw new RuntimeException("该课程已经上架，不需要重复上架");
        } else {
            // 4.修改课程上架时间和状态
            Date now = new Date();
            course.setStatus(Course.STATE_ON_LINE);
            course.setOnlineTime(now);
            courseService.updateById(course);
        }

        // 5.把课程需要搜索的关键字放入ES中
        CourseDoc courseDoc = new CourseDoc();
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        CourseSummary courseSummary = courseSummaryService.selectById(course.getId());
        CourseMarket courseMarket = courseMarketService.selectById(course.getId());
        BeanUtils.copyProperties(course,courseDoc);
        BeanUtils.copyProperties(courseSummary,courseDoc);
        BeanUtils.copyProperties(courseMarket,courseDoc);
        courseDoc.setCourseTypeName(courseType.getName());
        courseDoc.setChargeName(courseMarket.getCharge().intValue() == 1?"免费":"收费");
        courseDoc.setId(course.getId());
        JSONResult jsonResult = searchFeign.saveCourse(courseDoc);
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程发布失败！！");
        // 发送mq消息
        MessageSms messageSms = new MessageSms();
        messageSms.setContent("亲爱的用户您好，最新课程 <a href='http://course.ymcc.com:6002/detail.html?courseId=3'> java大神班 </a> 发布啦，点击课程了解详情");
        messageSms.setTitle("课程发布");
        messageSms.setUserId(1L);
        Date date = new Date();
        messageSms.setSendTime(date);
        Message<?> message = MessageBuilder.withPayload(messageSms).build();
        rocketMQTemplate.syncSend("topic-couseOnLine:tags-sms", message);

    }

    /*
     * @Title: offLineCourse
     * @Description: 课程下架
     * @Author: Mr.Jiang
     * @Version: 1.0
     * @Date:  2022/8/14 17:11
     * @Parameters: [courseId]
     * @Return void
     */
    @Override
    @Transactional
    public void offLineCourse(Long courseId) {
        // 1.参数校验
        AssertUtil.isNotNull(courseId, "课程ID不能为空");
        // 2.业务校验（查找的课程是否存在）
        Course course = courseService.selectById(courseId);
        AssertUtil.isNotNull(course, "你查找的课程不存在");
        // 3.若存在那么就查看他的状态
        boolean b = course.getStatus() == Course.STATE_ON_LINE;
        AssertUtil.isTrue(b, "该课程已经下架了哦");
        // 4.修改课程上架时间和状态
        Date now = new Date();
        course.setStatus(Course.STATE_OFF_LINE);
        course.setOnlineTime(now);
        courseService.updateById(course);
        // 准备做ES下架删除
        JSONResult jsonResult = searchFeign.delete(courseId);
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程下架失败！！");

    }

    @Override
    public CourseDetailInfoVo getdetailInfo(Long courseId) {
        // 0.非空校验
        AssertUtil.isNotNull(courseId,"课程ID不能为空");
        // 1.先查询课程
        Course course = courseService.selectById(courseId);
        // 1.1查询到课程之后有可能不存在
        AssertUtil.isNotNull(course,"课程不存在。请你留意后续更新");
        // 1.2查询到的课程可能还没有上架
        AssertUtil.isTrue(course.getStatus() == Course.STATE_ON_LINE,"您所查询的课程还没上架哦");
        // 2.再通过courseId查找courseMarket
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        // 3.查找课程详情
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        // 4通过中间表查找Teacher们
        Wrapper<CourseTeacher> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id",courseId);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(wrapper);
        List<Long> courseTeacherID = courseTeachers.stream().map(courseTeacher -> courseTeacher.getTeacherId()).collect(Collectors.toList());
        // 4.1 将得到的老师id查找老师
        List<Teacher> teachers = teacherService.selectBatchIds(courseTeacherID);
        // 5.课程章节
        Wrapper<CourseChapter> ChapterWrapper = new EntityWrapper<>();
        ChapterWrapper.eq("course_id",courseId);
        // 5.1得到所有的章节
        List<CourseChapter> courseChapters = courseChapterService.selectList(ChapterWrapper);
        // 5.5 将章节转换成Map
        Map<Long, CourseChapter> map = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        // 5.2通过course->media调用fegin接口查询到所有的视频（1.先在media微服务中根据courseId写一个查询课程视频的接口 2.再写一个api去调用）
        JSONResult courseVideo = mediaFeign.getCourseVideo(courseId);
        // 5.3断言(需要在看看)
        AssertUtil.isTrue(courseVideo.isSuccess(),courseVideo.getMessage());
        AssertUtil.isNotNull(courseVideo.getData(),"视频不见了");

        // 5.4将视频分别放在所对应的章节中（需要总结）
        List<MediaFile> mediaFiles = JSONObject.parseArray(courseVideo.getData().toString(), MediaFile.class);
        mediaFiles.stream().forEach(mediaFile->{
         map.get(mediaFile.getChapterId())
            .getMediaFiles()
            .add(mediaFile);
        });

        return new CourseDetailInfoVo(course,courseMarket,courseChapters,teachers,courseDetail);
    }
/*
* @Title: selectCourseInfosTotalAmount
* @Description: 这是为了渲染下单界面的
* @Author: Mr.Jiang
* @Version: 1.0
* @Date:  2022/8/18 0:51
* @Parameters: [courseIds]
* @Return cn.sunshine.ymcc.vo.CourseInfosTotalAmountVo
*/
    @Override
    public CourseInfosTotalAmountVo selectCourseInfosTotalAmount(String courseIds) {
        AssertUtil.isNotEmpty(courseIds,"您的请求参数有误，请重新输入");
        String[] split = courseIds.split(",");
        List<Course> courses = selectBatchIds(Arrays.asList(split));
        CourseInfosTotalAmountVo courseInfosTotalAmountVo = new CourseInfosTotalAmountVo();

        ArrayList<CourseInfosVo> courseInfos = new ArrayList<>();
        for (Course course : courses) {
            AssertUtil.isTrue(course.getStatus() == 1,"该课程资源不可用");
            CourseInfosVo courseInfosVo = new CourseInfosVo();
            CourseMarket courseMarket = courseMarketService.selectById(course.getId());
            courseInfosVo.setCourseMarket(courseMarket);
            courseInfosVo.setCourse(course);
            courseInfos.add(courseInfosVo);
            // 每次循环附加金额（思路很独特）
            courseInfosTotalAmountVo.setTotalAmount(courseInfosTotalAmountVo.getTotalAmount().add(courseMarket.getPrice()));
        }
        courseInfosTotalAmountVo.setCourseInfos(courseInfos);
        return courseInfosTotalAmountVo;
    }

}
